package com.gonsin.venus.sdk.client;

import com.gonsin.venus.sdk.GonsinConfig;
import com.gonsin.venus.sdk.exceptions.ApiException;
import com.gonsin.venus.sdk.exceptions.ErrorCodes;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * xToken和xKey的管理工具
 */
public class TokenManager {

    /**
     * xToken过期时间
     */
    private long expireTime;

    /**
     * xToken和xKey
     */
    private TokenBo tokenBo;

    /**
     * 初始化参数
     */
    private GonsinConfig config;

    /**
     * 是否已登录
     */
    private boolean logined;

    public TokenManager() {
    }

    /**
     * 获取xToken 和 xKey
     * @return
     */
    public synchronized TokenBo getToken() throws ApiException {
        if(tokenBo != null && expireTime > System.currentTimeMillis()){
            if(!logined){
                login();
            }
            return tokenBo;
        }
        requestTokenSync();
        return getToken();
    }

    protected void init(GonsinConfig config){
        this.config = config;
    }

    /**
     * 查询xkey 和 xtoken
     */
    private void requestTokenSync() throws ApiException {
        if(tokenBo == null){
            String url = "/PMwIvA74/ZwAqVSia.json";
            CloseableHttpClient client = HttpClientBuilder.create().build();
            HttpGet httpGet = new HttpGet(config.toUrl(url));
            try {
                HttpResponse response = client.execute(httpGet);
                if(response.getStatusLine().getStatusCode() != 200){
                    throw new ApiException(ErrorCodes.HTTP_ERROR, "获取Token失败");
                }
                InputStream input = response.getEntity().getContent();

                StringBuilder sb = new StringBuilder();
                String line;
                BufferedReader br = new BufferedReader(new InputStreamReader(input));
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                String str = sb.toString();

                log(str);

                JsonParser parser = new JsonParser();
                JsonElement element = parser.parse(str);
                JsonObject responseJson = element.getAsJsonObject();
                int status = responseJson.get("state").getAsInt();
                if(status != 200){
                    throw new ApiException(ErrorCodes.TOKEN_ERROR, "获取Token失败");
                }

                JsonObject dataJson = responseJson.get("data").getAsJsonObject();
                long expireTime = dataJson.get("expireTime").getAsLong();
                String xKey = dataJson.get("xkey").getAsString();
                String xToken = dataJson.get("xtoken").getAsString();
                this.tokenBo = new TokenBo();
                tokenBo.setXToken(xToken);
                this.expireTime = expireTime + System.currentTimeMillis();

                // 调用登录接口
                login();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            String url = "/PMwIvA74/XaO2bmah.json";
            CloseableHttpClient client = HttpClientBuilder.create().build();
            HttpGet httpGet = new HttpGet(config.toUrl(url));
            try {
                httpGet.addHeader("x-token", this.tokenBo.getXToken());
                HttpResponse response = client.execute(httpGet);
                if(response.getStatusLine().getStatusCode() != 200){
                    throw new ApiException(ErrorCodes.HTTP_ERROR, "获取Token失败");
                }
                InputStream input = response.getEntity().getContent();

                StringBuilder sb = new StringBuilder();
                String line;
                BufferedReader br = new BufferedReader(new InputStreamReader(input));
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                String str = sb.toString();
                log(str);

                JsonParser parser = new JsonParser();
                JsonElement element = parser.parse(str);
                JsonObject responseJson = element.getAsJsonObject();
                int status = responseJson.get("state").getAsInt();
                if(status != 200){
                    throw new ApiException(ErrorCodes.TOKEN_ERROR, "获取Token失败");
                }

                JsonObject dataJson = responseJson.get("data").getAsJsonObject();
                long expireTime = dataJson.get("expireTime").getAsLong();
                String xKey = dataJson.get("xkey").getAsString();
                String xToken = dataJson.get("xtoken").getAsString();
                tokenBo.setXToken(xToken);
                this.expireTime = expireTime + System.currentTimeMillis();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 打印日志
     * @param content
     */
    private void log(String content) {
        if(config.isLog()){
            System.out.println(content);
        }
    }


    /**
     * 登录
     */
    private void login() throws ApiException {
        String url = config.toUrl("/api/handle_login");
        CloseableHttpClient client = HttpClientBuilder.create().build();
        HttpPost post = new HttpPost(url);
        String response = null;
        try {
            List<NameValuePair> p = new ArrayList<>();
            p.add(new BasicNameValuePair("username", config.getUsername()));
            p.add(new BasicNameValuePair("password", config.getPassword()));
            post.setEntity(new UrlEncodedFormEntity(p));
            post.addHeader("x-token", tokenBo.getXToken());
            HttpResponse res = client.execute(post);

            InputStream input = res.getEntity().getContent();
            StringBuilder sb = new StringBuilder();
            String line;
            BufferedReader br = new BufferedReader(new InputStreamReader(input));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            String str = sb.toString();
            log(str);

            JsonParser parser = new JsonParser();
            JsonElement element = parser.parse(str);
            JsonObject responseJson = element.getAsJsonObject();
            int status = responseJson.get("state").getAsInt();
            if(status != 200){
                throw new ApiException(ErrorCodes.LOGIN_FAILED, "登录失败");
            }

            logined = true;

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 是否已初始化
     * @return
     */
    public boolean inited() {
        return config != null;
    }
}
